"""项目数据服务"""
import requests
from datetime import datetime, date
from typing import List, Dict, Any, Optional
from config.gitlab_config import GITLAB_CONFIG
from services.project_db_service import ProjectDBService
from utils.logger import sync_logger

class ProjectService:
    def __init__(self):
        self.base_url = f"{GITLAB_CONFIG['url']}/api/{GITLAB_CONFIG['api_version']}"
        self.headers = {'PRIVATE-TOKEN': GITLAB_CONFIG['token']}
        self.timeout = GITLAB_CONFIG['timeout']
        self.project_db = ProjectDBService()
    
    def get_project_details(self, project_id: int) -> Optional[Dict[str, Any]]:
        """获取项目详细信息"""
        try:
            url = f"{self.base_url}/projects/{project_id}"
            response = requests.get(url, headers=self.headers, timeout=self.timeout)
            if response.status_code == 200:
                return response.json()
            else:
                sync_logger.log_error(f"获取项目 {project_id} 详情失败: {response.status_code}")
                return None
        except Exception as e:
            sync_logger.log_error(f"获取项目 {project_id} 详情时发生错误: {e}")
            return None
    
    def get_project_branches(self, project_id: int) -> List[Dict[str, Any]]:
        """获取项目分支信息"""
        branches = []
        page = 1
        
        while True:
            try:
                url = f"{self.base_url}/projects/{project_id}/repository/branches"
                params = {'page': page, 'per_page': GITLAB_CONFIG['per_page']}
                response = requests.get(url, headers=self.headers, params=params, timeout=self.timeout)
                
                if response.status_code == 200:
                    page_branches = response.json()
                    if not page_branches:
                        break
                    branches.extend(page_branches)
                    page += 1
                else:
                    sync_logger.log_error(f"获取项目 {project_id} 分支列表失败: {response.status_code}")
                    break
            except Exception as e:
                sync_logger.log_error(f"获取项目 {project_id} 分支列表时发生错误: {e}")
                break
        
        return branches
    
    def get_project_tags(self, project_id: int) -> List[Dict[str, Any]]:
        """获取项目标签信息"""
        tags = []
        page = 1
        
        while True:
            try:
                url = f"{self.base_url}/projects/{project_id}/repository/tags"
                params = {'page': page, 'per_page': GITLAB_CONFIG['per_page']}
                response = requests.get(url, headers=self.headers, params=params, timeout=self.timeout)
                
                if response.status_code == 200:
                    page_tags = response.json()
                    if not page_tags:
                        break
                    tags.extend(page_tags)
                    page += 1
                else:
                    sync_logger.log_error(f"获取项目 {project_id} 标签列表失败: {response.status_code}")
                    break
            except Exception as e:
                sync_logger.log_error(f"获取项目 {project_id} 标签列表时发生错误: {e}")
                break
        
        return tags
    
    def get_project_merge_requests(self, project_id: int, state: str = 'all') -> List[Dict[str, Any]]:
        """获取项目合并请求信息"""
        merge_requests = []
        page = 1
        
        while True:
            try:
                url = f"{self.base_url}/projects/{project_id}/merge_requests"
                params = {
                    'page': page,
                    'per_page': GITLAB_CONFIG['per_page'],
                    'state': state
                }
                response = requests.get(url, headers=self.headers, params=params, timeout=self.timeout)
                
                if response.status_code == 200:
                    page_mrs = response.json()
                    if not page_mrs:
                        break
                    merge_requests.extend(page_mrs)
                    page += 1
                else:
                    sync_logger.log_error(f"获取项目 {project_id} 合并请求列表失败: {response.status_code}")
                    break
            except Exception as e:
                sync_logger.log_error(f"获取项目 {project_id} 合并请求列表时发生错误: {e}")
                break
        
        return merge_requests
    
    def get_project_issues(self, project_id: int, state: str = 'all') -> List[Dict[str, Any]]:
        """获取项目问题列表"""
        issues = []
        page = 1
        
        while True:
            try:
                url = f"{self.base_url}/projects/{project_id}/issues"
                params = {
                    'page': page,
                    'per_page': GITLAB_CONFIG['per_page'],
                    'state': state
                }
                response = requests.get(url, headers=self.headers, params=params, timeout=self.timeout)
                
                if response.status_code == 200:
                    page_issues = response.json()
                    if not page_issues:
                        break
                    issues.extend(page_issues)
                    page += 1
                else:
                    sync_logger.log_error(f"获取项目 {project_id} 问题列表失败: {response.status_code}")
                    break
            except Exception as e:
                sync_logger.log_error(f"获取项目 {project_id} 问题列表时发生错误: {e}")
                break
        
        return issues
    
    def calculate_project_statistics(self, project_id: int) -> Dict[str, Any]:
        """计算项目统计信息"""
        stats = {
            'project_id': project_id,
            'total_branches': len(self.get_project_branches(project_id)),
            'total_tags': len(self.get_project_tags(project_id)),
            'stats_date': date.today()
        }
        
        # 获取合并请求统计
        merge_requests = self.get_project_merge_requests(project_id)
        stats.update({
            'total_merge_requests': len(merge_requests),
            'open_merge_requests': len([mr for mr in merge_requests if mr['state'] == 'opened']),
            'closed_merge_requests': len([mr for mr in merge_requests if mr['state'] == 'closed']),
            'merged_merge_requests': len([mr for mr in merge_requests if mr['state'] == 'merged'])
        })
        
        # 获取问题统计
        issues = self.get_project_issues(project_id)
        stats.update({
            'total_issues': len(issues),
            'open_issues': len([issue for issue in issues if issue['state'] == 'opened']),
            'closed_issues': len([issue for issue in issues if issue['state'] == 'closed'])
        })
        
        return stats
    
    def calculate_activity_scores(self, project_id: int, stats: Dict[str, Any]) -> Dict[str, Any]:
        """计算项目活跃度评分"""
        # 计算提交频率得分 (0-100)
        commit_frequency_score = min(stats['total_commits'] / 100 * 100, 100) if 'total_commits' in stats else 0
        
        # 计算合并请求频率得分 (0-100)
        mr_frequency_score = min(stats['total_merge_requests'] / 50 * 100, 100)
        
        # 计算问题处理得分 (0-100)
        if stats['total_issues'] > 0:
            issue_handling_score = (stats['closed_issues'] / stats['total_issues']) * 100
        else:
            issue_handling_score = 0
        
        # 计算代码审查得分 (0-100)
        if stats['total_merge_requests'] > 0:
            code_review_score = (stats['merged_merge_requests'] / stats['total_merge_requests']) * 100
        else:
            code_review_score = 0
        
        # 计算总分 (加权平均)
        total_score = (
            commit_frequency_score * 0.3 +
            mr_frequency_score * 0.2 +
            issue_handling_score * 0.25 +
            code_review_score * 0.25
        )
        
        return {
            'project_id': project_id,
            'commit_frequency_score': commit_frequency_score,
            'mr_frequency_score': mr_frequency_score,
            'issue_handling_score': issue_handling_score,
            'code_review_score': code_review_score,
            'total_score': total_score,
            'score_date': date.today()
        }
    
    def sync_projects(self):
        """同步所有项目数据"""
        try:
            # 获取项目列表
            projects = self.get_all_projects()
            sync_logger.log_info(f"获取到 {len(projects)} 个项目")
            
            # 同步每个项目的数据
            for project in projects:
                project_id = project['id']
                sync_logger.log_info(f"开始同步项目 {project_id} 的数据")
                
                try:
                    # 1. 保存项目基本信息
                    self.project_db.save_project(project)
                    
                    # 2. 获取并保存项目统计信息
                    stats = self.calculate_project_statistics(project_id)
                    self.project_db.save_project_statistics(stats)
                    
                    # 3. 计算并保存项目活跃度评分
                    scores = self.calculate_activity_scores(project_id, stats)
                    self.project_db.save_activity_scores(scores)
                    
                except Exception as e:
                    sync_logger.log_error(f"同步项目 {project_id} 数据时发生错误: {e}")
                    continue  # 继续处理下一个项目
            
            sync_logger.log_info("同步任务完成")
            
        except Exception as e:
            sync_logger.log_error(f"同步项目数据时发生错误: {e}")
            raise 